﻿using UnityEngine;

namespace KaoticSSB
{
	/**
	 * \brief A small class that represents which joystick buttons are being held
	 */
	public class InputHelper
	{
		public class DirectionsHeld
		{
			public bool Left;
			public bool Right;
			public bool Down;
			public bool Up;

			/** Constructor */
			public DirectionsHeld()
			{
				Left = false;
				Right = false;
				Down = false;
				Up = false;
			}

			/** Helper functions */
			public bool IsDefaultHorizontal()
			{
				return (!Left && !Right);
			}			
			public bool IsDefaultVertical()
			{
				return (!Down && !Up);
			}
			public static bool HorizontalEquals(DirectionsHeld x, DirectionsHeld y)
			{
				return( ( x.Right == y.Right) &&( x.Left == y.Left ) );
			}
			public static bool VerticalEquals(DirectionsHeld x, DirectionsHeld y)
			{
				return( ( x.Up == y.Up) &&( x.Down == y.Down ) );
			}
		}

		public const float StickResetTime = 0.25f;

		public InputHelper()
		{
			mCurrentHorizontalStickResetTime = StickResetTime;
			mCurrentVerticalStickResetTime = StickResetTime;
			mDirections = new DirectionsHeld();
		}

		public void Update()
		{
			mCurrentHorizontalStickResetTime -= Time.deltaTime;
			mCurrentVerticalStickResetTime -= Time.deltaTime;
		}

		/**
		 * \brief Acts similar to GetKeyDown but for the left joystick
		 * This function allows you to get a "onKeyDown" type result, but also gives you a positive result on a fixed time interval
		 * This should be useful for allowing the user to hold down on menus
		 */
		public DirectionsHeld GetLeftJoystickDown(int playerIndex)
		{
			DirectionsHeld directions = new DirectionsHeld();
			int amountX = GetRoundedAxisAmount(Input.GetAxis ("Horizontal_Player_" + playerIndex));
			int amountY = GetRoundedAxisAmount(Input.GetAxis ("Vertical_Player_" + playerIndex));

			if(amountX == -1)
				directions.Left = true;
			else if(amountX == 1)
				directions.Right = true;
			if(amountY == -1)
				directions.Up = true;
			else if(amountY == 1)
				directions.Down = true;

			//if there was a direction and now there isn't, reset the directions
			if(!mDirections.IsDefaultHorizontal() && directions.IsDefaultHorizontal())
			{
				mCurrentHorizontalStickResetTime = 0;
			}
			if(!mDirections.IsDefaultVertical() && directions.IsDefaultVertical())
			{
				mCurrentVerticalStickResetTime = 0;
			}

			bool reset = false;
			// if the previous horizontal direction is different than the current
			// or if timer runs out
			if(mCurrentHorizontalStickResetTime <= 0.0f || !DirectionsHeld.HorizontalEquals(directions, mDirections)  )
			{
				mDirections.Right = directions.Right;
				mDirections.Left = directions.Left;
				mCurrentHorizontalStickResetTime = StickResetTime;
				reset = true;
			}
			else
			{
				directions.Right = false;
				directions.Left = false;
			}

			// if the previous vertical direction is different than the current
			// or if timer runs out
			if(mCurrentVerticalStickResetTime <= 0.0f || !DirectionsHeld.VerticalEquals(directions, mDirections) )
			{				
				mDirections.Down = directions.Down;
				mDirections.Up = directions.Up;
				mCurrentVerticalStickResetTime = StickResetTime;
				reset = true;
			}
			else
			{
				directions.Down = false;
				directions.Up = false;
			}

			if(reset)
			{
				return directions;
			}

			return new DirectionsHeld();
		}

		private float mCurrentHorizontalStickResetTime;
		private float mCurrentVerticalStickResetTime;
		private DirectionsHeld mDirections;

		private int GetRoundedAxisAmount(float value)
		{
			if(value >= 0.5)
				return 1;
			else if(value <= -0.5)
				return -1;
			else
				return 0;
		}
	}
}